/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.form.compat2.layouts;
import java.awt.*;
import java.beans.*;
import java.lang.reflect.InvocationTargetException;
import org.openide.explorer.propertysheet.editors.EnhancedPropertyEditor;
import org.openide.nodes.Node;
import org.openide.nodes.PropertySupport;
import org.netbeans.lib.awtextra.AbsoluteConstraints;
import org.netbeans.lib.awtextra.AbsoluteLayout;
import org.netbeans.modules.form.util2.NbVersion;
import org.netbeans.modules.form.util2.NbVersionNotCompatibleException;
import org.netbeans.modules.form.*;
import org.netbeans.modules.form.util.*;
/** A design-time support for AbsoluteLayout.
*
* @author Ian Formanek
*/
final public class DesignAbsoluteLayout extends DesignLayout {
/** A JDK 1.1. serial version UID */
static final long serialVersionUID = -1148154120636340460L;
/** Netbeans class version */
public static final NbVersion nbClassVersion = new NbVersion (1, 0);
/** Layout Properties */
final static String PROP_X = FormEditor.LAYOUT_PREFIX + "xPosition"; // NOI18N
final static String PROP_Y = FormEditor.LAYOUT_PREFIX + "yPosition"; // NOI18N
final static String PROP_WIDTH = FormEditor.LAYOUT_PREFIX + "widthSize"; // NOI18N
final static String PROP_HEIGHT = FormEditor.LAYOUT_PREFIX + "heightSize"; // NOI18N
/** bundle to obtain text information from */
private static final java.util.ResourceBundle bundle = org.openide.util.NbBundle.getBundle (DesignAbsoluteLayout.class);
/** icons for the Layout. */
static protected Image icon;
static protected Image icon32;
static {
icon = Toolkit.getDefaultToolkit ().getImage (
DesignAbsoluteLayout.class.getResource ("/org/netbeans/modules/form/resources/palette/absoluteLayout.gif")); // NOI18N
icon32 = Toolkit.getDefaultToolkit ().getImage (
DesignAbsoluteLayout.class.getResource ("/org/netbeans/modules/form/resources/palette/absoluteLayout32.gif")); // NOI18N
}
/** An icon of the design-layout. This icon will be used on the ComponentPalette
* for this layout's item.
* @param type the desired type of the icon (BeanInfo.ICON_???)
* @return layout's icon.
*/
public Image getIcon(int type) {
if ((type == java.beans.BeanInfo.ICON_COLOR_16x16) || (type == java.beans.BeanInfo.ICON_MONO_16x16))
return icon;
else
return icon32;
}
/** Assigns this DesignLayout to the specified RADVisualContainer.
* @param cont The RADVisualContainer that represents a container that will be
* managed by this layout or null as a notification that this layout
* is not a designLayout for its current container anymore
*/
public void setRADContainer (RADVisualContainer cont) {
if (cont == null) { // deattaching the layout
if ((designComponent != null) && (getMode() == DESIGN_MODE)) {
getContainer().remove(designComponent);
}
if (formListener != null) {
FormEditor.getFormSettings ().removePropertyChangeListener (formListener);
formListener = null;
}
return;
}
super.setRADContainer(cont);
if (cont != null) {
if (formListener == null) {
formListener = new PropertyChangeListener () {
public void propertyChange (PropertyChangeEvent evt) {
if ((evt.getPropertyName () == null) ||
(evt.getPropertyName ().equals (FormLoaderSettings.PROP_SHOW_GRID)) ||
(FormLoaderSettings.PROP_GRID_X.equals (evt.getPropertyName ())) ||
(FormLoaderSettings.PROP_GRID_Y.equals (evt.getPropertyName ()))) {
getContainerHelper ().validate();
getContainerHelper ().repaint ();
}
}
};
FormEditor.getFormSettings ().addPropertyChangeListener (formListener);
}
designComponent = new DesignAbsoluteComponent();
realLayout = new EnhancedAbsoluteLayout();
if (getMode() == DESIGN_MODE) {
getContainer().setLayout(new BorderLayout());
getContainer().add(designComponent, "Center"); // NOI18N
} else {
getContainer().setLayout(realLayout);
}
}
}
protected Container getContainerHelper () {
return getContainer ();
}
/** Sets the current mode of this layout.
* Descendants must override this method to provide any additional
* functionality needed when layout mode is switched.
* @see #DESIGN_MODE
* @see #REAL_MODE
* @see #getMode
*/
public void setMode(int mode) {
if (mode == getMode()) return;
super.setMode(mode);
if (mode == DESIGN_MODE) {
getContainer().removeAll();
RADVisualComponent[] children = getRADContainer().getSubComponents ();
getContainer().setLayout(new BorderLayout());
getContainer().add(designComponent, "Center"); // NOI18N
for (int i=0; i< children.length; i++) {
ConstraintsDescription cd = (ConstraintsDescription)children[i].getConstraints(DesignAbsoluteLayout.class);
designComponent.add(getFormManager ().getVisualRepresentation (children[i]), cd.getConstraintsObject ());
}
getContainer().validate();
getContainer().repaint ();
}
else {
RADVisualComponent[] children = getRADContainer().getSubComponents ();
designComponent.removeAll();
getContainer().remove(designComponent);
getContainer().setLayout(realLayout);
for (int i=0; i< children.length; i++) {
ConstraintsDescription cd = (ConstraintsDescription)children[i].getConstraints(DesignAbsoluteLayout.class);
getContainer().add(getFormManager ().getVisualRepresentation (children[i]), cd.getConstraintsObject ());
}
getContainer().validate();
getContainer().repaint ();
}
}
/** Returns a constraint to be used for adding a component to the
* specified position (e.g. in BorderLayout, the "North", "South", ...
* will be determined by the position in the container).
* The default implementation just returns the default constraints.
* A special constraints object will be returned for layouts that
* wish to set the position&size of the components rather than add
* with constraints.
* @param position The position within the container for which the
* constraints should be returned.
*/
public DesignLayout.ConstraintsDescription getConstraintsDescription(Point position) {
if (FormEditor.getFormSettings ().getShowGrid () &&
FormEditor.getFormSettings ().getApplyGridToPosition ())
{
int gridX = FormEditor.getFormSettings ().getGridX ();
int gridY = FormEditor.getFormSettings ().getGridY ();
int posX = position.x - (position.x % gridX);
int posY = position.y - (position.y % gridY);
return new AbsoluteConstraintsDescription (new Point (posX, posY));
}
else
return new AbsoluteConstraintsDescription(position);
}
/** A display name of the layout will be used for displaying the layout in
* the components hierarchy during design-time.
* @return layout's display name.
*/
public String getDisplayName() {
return "AbsoluteLayout"; // NOI18N
}
/** Returns the layout's properties for specified component.
* @param comp the RADVisualComponent of the component which properties we request
* @return the layout-specific properties for specified component
*/
public Node.Property[] getComponentProperties(RADVisualComponent comp) {
ConstraintsDescription cd = comp.getConstraints(DesignAbsoluteLayout.class);
if (cd == null) return new Node.Property[0];
AbsoluteConstraints ac = (AbsoluteConstraints)cd.getConstraintsObject();
if (ac == null) return new Node.Property[0];
final RADVisualComponent component = comp;
return new Node.Property[] {
new PropertySupport.ReadWrite (PROP_X, Integer.TYPE,
bundle.getString("PROP_absolute_x"), bundle.getString("HINT_absolute_x")) {
public Object getValue () throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
ConstraintsDescription acd = component.getConstraints(DesignAbsoluteLayout.class);
return new Integer(((AbsoluteConstraints)acd.getConstraintsObject()).x);
}
public void setValue (Object val) throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
if (val instanceof Integer) {
Object oldValue = getValue ();
AbsoluteConstraintsDescription acd =
(AbsoluteConstraintsDescription)component.getConstraints(DesignAbsoluteLayout.class);
acd.position.x = ((Integer)val).intValue();
Component visual = getFormManager ().getVisualRepresentation (component);
designComponent.remove(visual);
designComponent.add(visual, acd.getConstraintsObject());
designComponent.validate ();
firePropertyChange (component, PROP_X, oldValue, val);
}
else throw new IllegalArgumentException();
}
},
new PropertySupport.ReadWrite (PROP_Y, Integer.TYPE,
bundle.getString("PROP_absolute_y"), bundle.getString("HINT_absolute_y")) {
public Object getValue () throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
ConstraintsDescription acd = component.getConstraints(DesignAbsoluteLayout.class);
return new Integer(((AbsoluteConstraints)acd.getConstraintsObject()).y);
}
public void setValue (Object val) throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
if (val instanceof Integer) {
Object oldValue = getValue ();
AbsoluteConstraintsDescription acd =
(AbsoluteConstraintsDescription)component.getConstraints(DesignAbsoluteLayout.class);
acd.position.y = ((Integer)val).intValue();
Component visual = getFormManager ().getVisualRepresentation (component);
designComponent.remove(visual);
designComponent.add(visual, acd.getConstraintsObject());
designComponent.validate ();
firePropertyChange (component, PROP_Y, oldValue, val);
}
else throw new IllegalArgumentException();
}
},
new PropertySupport.ReadWrite (PROP_WIDTH, Integer.TYPE,
bundle.getString("PROP_absolute_width"), bundle.getString("HINT_absolute_width")) {
public Object getValue () throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
ConstraintsDescription acd = component.getConstraints(DesignAbsoluteLayout.class);
return new Integer(((AbsoluteConstraints)acd.getConstraintsObject()).width);
}
public void setValue (Object val) throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
if (val instanceof Integer) {
Object oldValue = getValue ();
AbsoluteConstraintsDescription acd =
(AbsoluteConstraintsDescription)component.getConstraints(DesignAbsoluteLayout.class);
acd.size.width = ((Integer)val).intValue();
Component visual = getFormManager ().getVisualRepresentation (component);
designComponent.remove(visual);
designComponent.add(visual, acd.getConstraintsObject());
designComponent.validate ();
firePropertyChange (component, PROP_WIDTH, oldValue, val);
}
else throw new IllegalArgumentException();
}
public PropertyEditor getPropertyEditor () {
return new SizeEditor ();
}
},
new PropertySupport.ReadWrite (PROP_HEIGHT, Integer.TYPE,
bundle.getString("PROP_absolute_height"), bundle.getString("HINT_absolute_height")) {
public Object getValue () throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
ConstraintsDescription acd = component.getConstraints(DesignAbsoluteLayout.class);
return new Integer(((AbsoluteConstraints)acd.getConstraintsObject()).height);
}
public void setValue (Object val) throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
if (val instanceof Integer) {
Object oldValue = getValue ();
AbsoluteConstraintsDescription acd =
(AbsoluteConstraintsDescription)component.getConstraints(DesignAbsoluteLayout.class);
acd.size.height = ((Integer)val).intValue();
Component visual = getFormManager ().getVisualRepresentation (component);
designComponent.remove(visual);
designComponent.add(visual, acd.getConstraintsObject());
designComponent.validate ();
firePropertyChange (component, PROP_HEIGHT, oldValue, val);
}
else throw new IllegalArgumentException();
}
public PropertyEditor getPropertyEditor () {
return new SizeEditor ();
}
}
};
}
/** Returns a class of the layout that this DesignLayout represents (e.g.
* returns FlowLayout.class from DesignFlowLayout).
* @return a class of the layout represented by this DesignLayout or null if the
* design layout does not represent a "real" layout (e.g. support layouts for JTabbedPane, ...)
*/
public Class getLayoutClass() {
return AbsoluteLayout.class;
}
// -----------------------------------------------------------------------------
// Child components management
/** Adds specified component to this layout. The constraints for the component
* are acquired from the component by method getConstraints().
* If the getConstraints() returns null, a new constraints should be
* synthesized, and set in the component via setConstraints().
* @param comp The component to add
* @see RADVisualComponent#getConstraints
* @see RADVisualComponent#setConstraints
* @see #removeComponent
*/
public void addComponent (RADVisualComponent comp) {
ConstraintsDescription cd = comp.getConstraints(DesignAbsoluteLayout.class);
if (cd == null) {
cd = new AbsoluteConstraintsDescription (new Point(0, 0));
comp.setConstraints(DesignAbsoluteLayout.class, cd);
}
AbsoluteConstraints constr = (AbsoluteConstraints)cd.getConstraintsObject();
Component visual = getFormManager ().getVisualRepresentation (comp);
if (getMode() == DESIGN_MODE) {
designComponent.add(visual, constr);
} else {
getContainer().add(visual, constr);
}
}
/** Removes specified component from this layout.
* @param comp The component to remove
* @see #addComponent
*/
public void removeComponent (RADVisualComponent comp) {
Component visual = getFormManager ().getVisualRepresentation (comp);
if (getMode() == DESIGN_MODE)
designComponent.remove(visual);
else
getContainer().remove(visual);
}
/** Updates the layout - readds all the visual components to reflect any global or
* ordering changes.
*/
public void updateLayout () {
if (getMode() == DESIGN_MODE)
designComponent.removeAll ();
else
getContainer().removeAll ();
RADVisualComponent[] children = getRADContainer ().getSubComponents ();
for (int i=0; i < children.length; i++)
addComponent (children[i]);
if (getMode() == DESIGN_MODE) {
designComponent.validate ();
designComponent.repaint ();
} else {
getContainer ().validate ();
getContainer ().repaint ();
}
}
// -----------------------------------------------------------------------------
// Drag'n'drop support
/** A design layout that supports moving components should redefine
* this method and return true.
* @return true if the design layout supports moving, false otherwise
* @see #moveTo
*/
public boolean canMove () {
return (getMode () == DESIGN_MODE);
}
/** A design layout that supports moving components should redefine
* this method to modify the constraints according to the supplied
* delta positions (difference between the old and the new position).
* @param desc the constraints to move from
* @param deltaX the delat move in x axis
* @param deltaY the delta move in y axis
* @param hotSpot The hotspot on the component (the point where the user started
* the drag on the component)
* @return the new modified ConstraintsDescription
* @see #canMove
*/
public ConstraintsDescription moveTo (ConstraintsDescription desc, int deltaX, int deltaY, Point hotSpot) {
Dimension size = ((AbsoluteConstraintsDescription)desc).size;
if (FormEditor.getFormSettings ().getShowGrid () &&
FormEditor.getFormSettings ().getApplyGridToPosition ())
{
int gridX = FormEditor.getFormSettings ().getGridX ();
int gridY = FormEditor.getFormSettings ().getGridY ();
int posX = deltaX + gridX/2 - ((deltaX + gridX/2) % gridX);
int posY = deltaY + gridY/2 - ((deltaY + gridY/2) % gridY);
return new AbsoluteConstraintsDescription (new Point (posX, posY),
new Dimension (size.width, size.height));
}
else
return new AbsoluteConstraintsDescription (new Point (deltaX, deltaY),
new Dimension (size.width, size.height));
}
/** A design layout that supports resizing components should redefine
* this method and return true.
* The resizing includes a initial drag-resize when adding a new component.
* @return true if the design layout supports resizing, false otherwise
* @see #resizeTo
*/
public boolean canResize () {
return (getMode () == DESIGN_MODE);
}
/** A design layout that supports resizing components should redefine
* this method to modify the constraints according to the supplied
* new size.
* @param desc the constraints to resize from
* @param width the width to resize to
* @param height the height to resize to
* @return the new modified ConstraintsDescription
* @see #canResize
*/
public ConstraintsDescription resizeTo (ConstraintsDescription desc, int width, int height) {
Point position = ((AbsoluteConstraintsDescription)desc).position;
if (FormEditor.getFormSettings ().getShowGrid () &&
FormEditor.getFormSettings ().getApplyGridToSize ())
{
int gridX = FormEditor.getFormSettings ().getGridX ();
int gridY = FormEditor.getFormSettings ().getGridY ();
int newWidth = width - (width % gridX);
int newHeight = height - (height % gridY);
return new AbsoluteConstraintsDescription (new Point (position.x, position.y),
new Dimension (newWidth, newHeight));
}
else
return new AbsoluteConstraintsDescription (new Point (position.x, position.y),
new Dimension (width, height));
}
/** A design layout that supports *BOTH* resizing and moving components
* should redefine this method to modify the constraints according to the supplied
* new bounds.
* @param desc the constraints to resize from
* @param bounds the bounds to resize to
* @see #canMove
* @see #canResize
*/
public ConstraintsDescription resizeToBounds (ConstraintsDescription desc, Rectangle bounds) {
if (FormEditor.getFormSettings ().getShowGrid () &&
FormEditor.getFormSettings ().getApplyGridToSize ())
{
int gridX = FormEditor.getFormSettings ().getGridX ();
int gridY = FormEditor.getFormSettings ().getGridY ();
int posX = bounds.x - (bounds.x % gridX);
int posY = bounds.y - (bounds.y % gridY);
int posW = bounds.x + bounds.width;
int posH = bounds.y + bounds.height;
posW = posW - (posW % gridX);
posH = posH - (posH % gridY);
int newWidth = posW - posX;
int newHeight = posH - posY;
return new AbsoluteConstraintsDescription (new Point (posX, posY),
new Dimension (newWidth, newHeight));
}
else
return new AbsoluteConstraintsDescription (new Point (bounds.x, bounds.y),
new Dimension (bounds.width, bounds.height));
}
/** Called to inform the Layout that it should provide a design-time visual
* feedback for a "move" action of the specified comp to the specified constraints.
* @param comp The RADVisualComponent that is being dragged
* @param desc The "drag to" constraints or null for ending the marking operation
*/
public void markMoveTo (RADVisualComponent comp, ConstraintsDescription desc) {
if (getMode() == DESIGN_MODE) {
if (desc == null) // clearing the mark
designComponent.setMarkRect (null);
else {
AbsoluteConstraints ac = (AbsoluteConstraints) desc.getConstraintsObject ();
int width, height;
Component visual = comp.getComponent ();
Dimension size = visual.getSize ();
width = ac.width;
if (width == -1)
width = size.width;
height = ac.height;
if (height == -1)
height = size.height;
designComponent.setMarkRect (new Rectangle (ac.x, ac.y, width, height));
}
}
}
/** Called to inform the Layout that it should provide a design-time visual
* feedback for a "resize" action to the specified constraints.
* @param desc The "resize to" constraints or null to notify about cancelling the resize operation
*/
public void markResizeTo (ConstraintsDescription desc) {
if (getMode() == DESIGN_MODE) {
if (desc == null) // clearing the mark
designComponent.setMarkRect (null);
else {
AbsoluteConstraints ac = (AbsoluteConstraints) desc.getConstraintsObject ();
if ((ac.width != -1) && (ac.height != -1))
designComponent.setMarkRect (new Rectangle (ac.x, ac.y, ac.width, ac.height));
}
}
}
// -----------------------------------------------------------------------------
// Code generation
/** Generates the code for initialization of this layout, e.g. panel1.setLayout (new BorderLayout ());.
* @param cont The container that is managed by this layout
* @return the init code for the layout or null if it should not be generated
*/
public String generateInitCode(RADVisualContainer cont) {
LayoutManager defaultLM = null;
try {
Container defaultCont = (Container)BeanSupport.getDefaultInstance (cont.getBeanClass ());
if (defaultCont != null) defaultLM = defaultCont.getLayout ();
if ((defaultLM == null) && FormEditor.getFormSettings ().isNullLayout ()) {
return null; // the default layout is the same as current settings => no need to generate layout
}
} catch (Exception e) {
if (Boolean.getBoolean ("netbeans.debug.exceptions")) e.printStackTrace (); // NOI18N
// ok, no default
}
if (defaultLM != null) {
if (defaultLM.getClass ().equals (AbsoluteLayout.class)) {
if (!FormEditor.getFormSettings ().isNullLayout ()) {
return null; // the default layout is the same as current settings => no need to generate layout
}
}
}
StringBuffer buf = new StringBuffer();
buf.append(createContainerGenName(cont));
if (FormEditor.getFormSettings ().isNullLayout ()) { // [PENDING - layout's generateNullLayout property instead ???]
buf.append("setLayout (null);\n"); // NOI18N
} else {
buf.append("setLayout (new org.netbeans.lib.awtextra.AbsoluteLayout ());\n"); // NOI18N
}
return buf.toString();
}
/** Generates the code for adding specified component to this layout.
* @param comp The component to be added to this layout
* @param cont The container that is managed by this layout
*/
public String generateComponentCode(RADVisualContainer cont, RADVisualComponent comp) {
ConstraintsDescription cd = comp.getConstraints(DesignAbsoluteLayout.class);
if (cd == null) return "// "+bundle.getString ("MSG_ErrorGeneratingCode");
AbsoluteConstraints ac = (AbsoluteConstraints)cd.getConstraintsObject();
if (ac == null) return "// "+bundle.getString ("MSG_ErrorGeneratingCode");
StringBuffer buf = new StringBuffer();
if (FormEditor.getFormSettings ().isNullLayout ()) { // [PENDING - layout's generateNullLayout property instead ???]
buf.append(createContainerGenName(cont));
buf.append("add ("); // NOI18N
buf.append(comp.getName());
buf.append(");\n"); // NOI18N
buf.append(comp.getName());
if ((ac.getWidth () == -1) && (ac.getHeight () == -1)) { // preferred size used ==>> generate setLocations and setSize
buf.append(".setLocation ("); // NOI18N
buf.append(ac.x);
buf.append(", "); // NOI18N
buf.append(ac.y);
buf.append(");\n"); // NOI18N
buf.append(comp.getName());
buf.append(".setSize ("); // NOI18N
buf.append(comp.getName());
buf.append(".getPreferredSize ());\n"); // NOI18N
} else { // not complete preferred size, either both width and height or one of them is specified ==>> generate setBounds
buf.append(".setBounds ("); // NOI18N
buf.append(ac.x);
buf.append(", "); // NOI18N
buf.append(ac.y);
buf.append(", "); // NOI18N
if (ac.width != -1) {
buf.append(ac.width);
} else {
buf.append(comp.getName());
buf.append(".getPreferredSize ().width"); // NOI18N
}
buf.append(", "); // NOI18N
if (ac.height != -1) {
buf.append(ac.height);
} else {
buf.append(comp.getName());
buf.append(".getPreferredSize ().height"); // NOI18N
}
buf.append(");\n"); // NOI18N
}
} else {
buf.append(createContainerGenName(cont));
buf.append("add ("); // NOI18N
buf.append(comp.getName());
buf.append(", new org.netbeans.lib.awtextra.AbsoluteConstraints ("); // NOI18N
buf.append(ac.x);
buf.append(", "); // NOI18N
buf.append(ac.y);
buf.append(", "); // NOI18N
buf.append(ac.width);
buf.append(", "); // NOI18N
buf.append(ac.height);
buf.append("));\n"); // NOI18N
}
return buf.toString();
}
// -----------------------------------------------------------------------------
// Serialization
/** Writes the object to the stream.
* @param oo output stream to write to
* @exception IOException Includes any I/O exceptions that may occur
*/
public void writeExternal (java.io.ObjectOutput oo)
throws java.io.IOException {
// store version
oo.writeObject (nbClassVersion);
}
/** Reads the object from stream.
* @param oi input stream to read from
* @exception IOException Includes any I/O exceptions that may occur
* @exception ClassNotFoundException if the class of the read object is not found
*/
public void readExternal (java.io.ObjectInput oi)
throws java.io.IOException, ClassNotFoundException {
org.netbeans.modules.form.FormUtils.DEBUG(">> DesignAbsoluteLayout: readExternal: START"); // NOI18N
// check the version
NbVersion classVersion = (NbVersion) oi.readObject ();
if (!nbClassVersion.isCompatible (classVersion))
throw new NbVersionNotCompatibleException (classVersion, nbClassVersion);
org.netbeans.modules.form.FormUtils.DEBUG("<< DesignAbsoluteLayout: readExternal: END"); // NOI18N
}
// -----------------------------------------------------------------------------
// constraints innerclass
/** The ConstraintsDescription class encapsulates constraints data and
* operations on a constraints that will be used for adding components
* to the layout.
*/
final public static class AbsoluteConstraintsDescription extends DesignLayout.ConstraintsDescription {
/** A JDK 1.1. serial version UID */
static final long serialVersionUID = 1265127948437909789L;
/** Netbeans class version */
public static final NbVersion nbClassVersion = new NbVersion (1, 0);
/** For externalization only */
public AbsoluteConstraintsDescription() {
}
public AbsoluteConstraintsDescription(Point pos) {
this (pos, new Dimension (-1, -1));
}
public AbsoluteConstraintsDescription(Point pos, Dimension dim) {
position = pos;
size = dim;
}
public String getConstraintsString() {
return "[x="+position.x+", y="+position.y+", width="+size.width+", height="+size.height+"]"; // NOI18N
}
public Object getConstraintsObject() {
return new AbsoluteConstraints (position, size);
}
// -----------------------------------------------------------------------------
// Serialization
/** Writes the object to the stream.
* @param oo output stream to write to
* @exception IOException Includes any I/O exceptions that may occur
*/
public void writeExternal (java.io.ObjectOutput oo)
throws java.io.IOException {
// store version
oo.writeObject (nbClassVersion);
oo.writeObject (size);
oo.writeObject (position);
}
/** Reads the object from stream.
* @param oi input stream to read from
* @exception IOException Includes any I/O exceptions that may occur
* @exception ClassNotFoundException if the class of the read object is not found
*/
public void readExternal (java.io.ObjectInput oi)
throws java.io.IOException, ClassNotFoundException {
org.netbeans.modules.form.FormUtils.DEBUG(">> AbsoluteConstraintsDescription: readExternal: START"); // NOI18N
// check the version
NbVersion classVersion = (NbVersion) oi.readObject ();
if (!nbClassVersion.isCompatible (classVersion))
throw new NbVersionNotCompatibleException (classVersion, nbClassVersion);
size = (Dimension) oi.readObject ();
position = (Point) oi.readObject ();
org.netbeans.modules.form.FormUtils.DEBUG("<< AbsoluteConstraintsDescription: readExternal: END"); // NOI18N
}
// -----------------------------------------------------------------------------
// XML Persistence
/** Called to load property value from specified XML subtree. If succesfully loaded,
* the value should be available via the getValue method.
* An IOException should be thrown when the value cannot be restored from the specified XML element
* @param element the XML DOM element representing a subtree of XML from which the value should be loaded
* @exception IOException thrown when the value cannot be restored from the specified XML element
*/
public void readFromXML (org.w3c.dom.Node element) throws java.io.IOException {
if (!XML_ABSOLUTE_CONSTRAINTS.equals (element.getNodeName ())) {
throw new java.io.IOException ();
}
org.w3c.dom.NamedNodeMap attributes = element.getAttributes ();
org.w3c.dom.Node xNode = attributes.getNamedItem (ATTR_X);
org.w3c.dom.Node yNode = attributes.getNamedItem (ATTR_Y);
org.w3c.dom.Node wNode = attributes.getNamedItem (ATTR_W);
org.w3c.dom.Node hNode = attributes.getNamedItem (ATTR_H);
if ((xNode != null) && (yNode != null)) position = new Point (Integer.parseInt (xNode.getNodeValue ()), Integer.parseInt (yNode.getNodeValue ()));
if ((wNode != null) && (hNode != null)) size = new Dimension (Integer.parseInt (wNode.getNodeValue ()), Integer.parseInt (hNode.getNodeValue ()));
}
/** Called to store current property value into XML subtree. The property value should be set using the
* setValue method prior to calling this method.
* @param doc The XML document to store the XML in - should be used for creating nodes only
* @return the XML DOM element representing a subtree of XML from which the value should be loaded or null
* if the value does not need to save any additional data and can be created using the default constructor
*/
public org.w3c.dom.Node storeToXML(org.w3c.dom.Document doc) {
org.w3c.dom.Element el = doc.createElement (XML_ABSOLUTE_CONSTRAINTS);
el.setAttribute (ATTR_X, Integer.toString (position.x));
el.setAttribute (ATTR_Y, Integer.toString (position.y));
el.setAttribute (ATTR_W, Integer.toString (size.width));
el.setAttribute (ATTR_H, Integer.toString (size.height));
return el;
}
public static final String XML_ABSOLUTE_CONSTRAINTS = "AbsoluteConstraints"; // NOI18N
public static final String ATTR_X = "x"; // NOI18N
public static final String ATTR_Y = "y"; // NOI18N
public static final String ATTR_W = "width"; // NOI18N
public static final String ATTR_H = "height"; // NOI18N
Dimension size;
Point position;
}
// -----------------------------------------
// inner classes
/** The design component for AbsolutLayout */
final public static class DesignAbsoluteComponent extends Container {
/** generated Serialized Version UID */
static final long serialVersionUID = -6053097200817565615L;
private Rectangle markRect = null;
private Component markComponent = null;
FormLoaderSettings formSettings = FormEditor.getFormSettings ();
GridInfo grid;
/** Constructs a new DesignAbsoluteComponent */
public DesignAbsoluteComponent () {
setLayout (new EnhancedAbsoluteLayout ());
grid = new GridInfo (formSettings.getGridX (), formSettings.getGridY ());
}
static void drawDots (Graphics g, int x, int y, int width, int height) {
// draw upper horizontal lines
for (int i = x; i <= x + width; i+=2)
g.drawLine (i, y, i, y);
// draw left vertical lines
for (int i = y; i <= y + height; i+=2)
g.drawLine (x, i, x, i);
int startX = x;
if (height % 2 != 0) startX += 1;
int startY = y;
if (width % 2 != 0) startY += 1;
// draw lower horizontal lines
for (int i = startX; i <= x + width; i+=2)
g.drawLine (i, y + height, i, y + height);
// draw right vertical lines
for (int i = startY; i <= y + height; i+=2)
g.drawLine (x + width, i, x + width, i);
}
void setMarkRect (Rectangle rect) {
if ((markRect == null) && (rect == null)) return;
final int borderSize = FormEditor.getFormSettings ().getSelectionBorderSize ();
if (markRect == null) {
add (markComponent = new Component () {
public void paint (Graphics g) {
Dimension size = getSize ();
g.setColor (FormEditor.getFormSettings ().getDragBorderColor ());
for (int i = borderSize / 2; i < borderSize; i++)
drawDots (g, i, i, size.width - 2*i - 1, size.height - 2*i - 1);
}
},
new AbsoluteConstraints (rect.x - borderSize, rect.y - borderSize,
rect.width + 2*borderSize, rect.height + 2*borderSize));
}
markRect = rect;
if (markRect == null) {
remove (markComponent);
} else {
remove (markComponent);
add (markComponent,
new AbsoluteConstraints (rect.x - borderSize, rect.y - borderSize,
rect.width + 2*borderSize, rect.height + 2*borderSize));
}
validate ();
if (markRect == null) {
repaint ();
}
}
public void paint(Graphics g) {
// paint grid
if (formSettings.getShowGrid ()) {
Dimension size = getSize ();
if ((formSettings.getGridX () != grid.getGridX ()) ||
(formSettings.getGridY () != grid.getGridY ()))
grid = new GridInfo (formSettings.getGridX (), formSettings.getGridY ());
FormUtils.paintGrid (this, g, grid, 0, 0, size.width, size.height);
}
super.paint(g);
}
}
/** This enhancement recognizes "selected" components and layouts them bigger, so that
* the selection border does not consume the inside area of the component
*/
static class EnhancedAbsoluteLayout extends AbsoluteLayout {
/** generated Serialized Version UID */
static final long serialVersionUID = 6256206967775931128L;
/** Lays out the container in the specified panel.
* @param parent the component which needs to be laid out
*/
public void layoutContainer(Container parent) {
int borderSize = FormEditor.getFormSettings ().getSelectionBorderSize ();
for (java.util.Enumeration e = constraints.keys(); e.hasMoreElements();) {
Component comp = (Component)e.nextElement();
AbsoluteConstraints ac = (AbsoluteConstraints)constraints.get(comp);
Dimension size = comp.getPreferredSize();
int x = ac.x;
int y = ac.y;
int width = ac.getWidth ();
if (width == -1) width = size.width;
int height = ac.getHeight ();
if (height == -1) height = size.height;
/* if (comp instanceof Selection) {
if (((Selection)comp).isSelected ()) {
if (ac.getWidth () != -1)
width += 2 * borderSize;
if (ac.getHeight () != -1)
height += 2 * borderSize;
x -= borderSize;
y -= borderSize;
}
}*/
comp.setBounds(x, y, width, height);
}
}
}
// -----------------------------------------------------------------------------
// Innerclasses
public static class SizeEditor
extends java.beans.PropertyEditorSupport
implements EnhancedPropertyEditor
{
/** Display Names for alignment. */
protected static final String NAME_PREFERRED = bundle.getString ("VALUE_absolute_preferred");
/**
* @return Returns custom property editor to be showen inside the property
* sheet.
*/
public Component getInPlaceCustomEditor () {
return null;
}
/**
* @return true if this PropertyEditor provides an enhanced in-place custom
* property editor, false otherwise
*/
public boolean hasInPlaceCustomEditor () {
return false;
}
/**
* @return true if this property editor provides tagged values and
* a custom strings in the choice should be accepted too, false otherwise
*/
public boolean supportsEditingTaggedValues () {
return true;
}
/** @return names of the possible directions */
public String[] getTags () {
return new String[] { NAME_PREFERRED };
}
/** @return text for the current value */
public String getAsText () {
int value = ((Integer)getValue ()).intValue ();
if (value == -1) return NAME_PREFERRED;
else return "" +value; // NOI18N
}
/** Setter.
* @param str string equal to one value from directions array
*/
public void setAsText (String str) {
if (str.equals (NAME_PREFERRED)) {
setValue (new Integer (-1));
}
else {
try {
setValue (new Integer (Integer.parseInt (str)));
} catch (NumberFormatException e) {
// what can we do, ignore it...
}
}
}
public String getJavaInitializationString () {
int value = ((Integer)getValue ()).intValue ();
return "" + value; // NOI18N
}
}
// -----------------------------------------
// private area
/** The real BorderLayout LayoutManager thaw works in real-layout mode*/
transient private AbsoluteLayout realLayout;
/** The layout-design mode component */
transient private DesignAbsoluteComponent designComponent;
/** The listener on FormSettings - for showGrid property changes */
transient private PropertyChangeListener formListener;
transient private boolean generateNullLayout = true;
}
/*
* Log
* 24 Gandalf 1.23 1/12/00 Ian Formanek NOI18N
* 23 Gandalf 1.22 12/14/99 Pavel Buzek
* 22 Gandalf 1.21 12/13/99 Pavel Buzek copy/paste operations
* handled properly (esp. painting)
* 21 Gandalf 1.20 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 20 Gandalf 1.19 9/24/99 Ian Formanek Smarter code generation
* - fixes bug 4016 - The setLayout code should not be generated if the
* layout is already set on the container to prevent loosing components
* already on the panel.
* 19 Gandalf 1.18 9/24/99 Ian Formanek generateInitCode method
* clarified
* 18 Gandalf 1.17 9/15/99 Ian Formanek Fixed bug 3858 - Form
* with NullPointer layout still has the getContentPane ().setLayout (new
* om.netbeans.developer.awt.AbsoluteLayout ()); line.
* 17 Gandalf 1.16 9/12/99 Ian Formanek Fixed bug 3530 - We do
* not support having a null layout.
* 16 Gandalf 1.15 9/9/99 Ian Formanek AbsoluteLayout changes
* 15 Gandalf 1.14 7/31/99 Ian Formanek Cleaned up comments
* 14 Gandalf 1.13 7/13/99 Ian Formanek XML Persistence
* 13 Gandalf 1.12 6/30/99 Ian Formanek reflected change in
* enhanced property editors
* 12 Gandalf 1.11 6/27/99 Ian Formanek Removed indent parameter
* from code generation methods
* 11 Gandalf 1.10 6/10/99 Ian Formanek Regeneration on layout
* changes
* 10 Gandalf 1.9 6/8/99 Ian Formanek ---- Package Change To
* org.openide ----
* 9 Gandalf 1.8 5/31/99 Ian Formanek Design/Test Mode
* 8 Gandalf 1.7 5/17/99 Ian Formanek Generates code for old
* AbsoluteLayout location (org.netbeans.lib.awtextra instead of
* org.netbeans.ide.awt) which is kinda ugly, but necessary because of
* backward compatibility
* 7 Gandalf 1.6 5/15/99 Ian Formanek
* 6 Gandalf 1.5 5/12/99 Ian Formanek
* 5 Gandalf 1.4 5/11/99 Ian Formanek Build 318 version
* 4 Gandalf 1.3 5/10/99 Ian Formanek
* 3 Gandalf 1.2 5/4/99 Ian Formanek package change
* (formeditor -> ..)
* 2 Gandalf 1.1 3/29/99 Ian Formanek Uses FormUtils.DEBUG to
* print messages
* 1 Gandalf 1.0 3/28/99 Ian Formanek
* $
*/